
package com.zy.je.common.core.model;

import com.zy.je.common.core.utils.reflection.Fn;
import com.zy.je.common.core.utils.reflection.Reflection;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.SuperBuilder;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.convert.ConvertUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zy
 * 状态计算器
 */
@Slf4j
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@Data
public class FnCalculator<T, V, R> {
    private T data;
    private List<Fn<T, V>> fns;
    private Fn<FnCalculator<T, V, R>, R> calcFn;

    public R calc() {
        return calcFn.apply(this);
    }

    public boolean has(Fn<T, V> fn) {
        if (null == data) {
            return false;
        }
        return ConvertUtil.toBigDecimal(fn.apply(this.data), BigDecimal.ZERO).compareTo(BigDecimal.ZERO) > 0;
    }

    public boolean only(Fn<T, V> fn) {
        return has(fn)
                && fns.stream()
                .filter(it -> !Reflection.fnToFieldName(it).equals(Reflection.fnToFieldName(fn)))
                .noneMatch(this::has);
    }

    public boolean only(List<Fn<T, V>> hasFns) {
        List<Fn<T, V>> otherFns = fns.stream()
                .filter(it -> hasFns.stream()
                        .noneMatch(hasFn -> Reflection.fnToFieldName(it).equals(Reflection.fnToFieldName(hasFn))))
                .toList();

        return hasFns.stream().allMatch(this::has)
                && otherFns.stream().noneMatch(this::has);
    }



    // for test   -----------------------------------------------------------------
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    @Getter
    @Setter
    static class TestCountOutModel {
        //0：执行中，1：完成，2：撤销
        @ApiModelProperty(value = "执行中的数量")
        private Integer executing;
        @ApiModelProperty(value = "完成的数量")
        private Integer finish;
        @ApiModelProperty(value = "撤销的数量")
        private Integer cancel;

      enum ExecuteState {
            执行中, 完成, 撤销
        }
    }

    public static void main(String[] args) {
        TestCountOutModel stateCount = TestCountOutModel.builder()
//                .executing(2)
                .cancel(1)
//                .finish(4)
                .build();

        FnCalculator<TestCountOutModel, Integer, TestCountOutModel.ExecuteState> statusCalculator = FnCalculator.<TestCountOutModel, Integer, TestCountOutModel.ExecuteState>builder()
                .data(stateCount)
                .fns(new ArrayList<>() {{
                    add(TestCountOutModel::getExecuting);
                    add(TestCountOutModel::getFinish);
                    add(TestCountOutModel::getCancel);
                }})
                .calcFn((c) -> {
                    //1、存在 执行中-->执行中
                    //2、存在 完成-->完成
                    //3、全为 已撤销-->撤销
                    //4、其他情况 -->撤销
                    if (c.has(TestCountOutModel::getExecuting)) {
                        return TestCountOutModel.ExecuteState.执行中;
                    }
                    if (c.has(TestCountOutModel::getFinish)) {
                        return TestCountOutModel.ExecuteState.完成;
                    }
                    if (c.only(TestCountOutModel::getCancel)) {
                        return TestCountOutModel.ExecuteState.撤销;
                    }
                    return TestCountOutModel.ExecuteState.撤销;
                })
                .build();

        TestCountOutModel.ExecuteState calc = statusCalculator.calc();

        log.debug("{}....", calc);
    }


}
